# 1.1.1 字符串型（str 类型）
# 字符串类型是 Python 语言中最常见的数据类型。字符串是由一组字符构成的序列，
#Python 的字符串不支持动态修改，是不可变的。
#用单引号、双引号或三引号括起来的任意文本称为字符串。使用单引号或双引号括起来
#的字符串只能写在一行。
#练习：创建字符串并打印在屏幕。


print('123456')
print("Software and Big Data")
print('''cloud computing----
 the delivery of different services through the Internet''')
print('He said, "I learn Python".')

print('*' * 100)

#1.1.2 int type
# 整型用来表示程序中用到的整数。整型数据包括：十进制整数、八进制整数、十六进制
#整数、二进制整数。Python 语言中整数的取值范围不受限制，不会受到机器字长的影响，只
#与内存有关。换言之，只要内存足够大，整型数可以表示任意大小的整数（包括正整数和负
#整数）。
# 练习：使用整数描述学生年龄、学制和班级人数信息。
print('年龄:',20)
print('学制:', 3)
print('班级人数:',22)

print('*' * 100)

# 2. 其他进制整数
#有的时候，需要用 Python 处理二进制数据，比如存取文件等操作。Python 没有二进制
#类型，但可以将十进制数据转换成二进制，并用字符串类型来存储二进制数据。
#二进制整数以 0b 或 0B 为前缀，用正负号、数码 0 和 1 表示，例如：0b10111、-0B1101、
#0b0，前缀不能省略。
#除了二进制，Python 中可以表示八进制、十六进制整数。八进制整数以 0o 或 0O 为前
#缀，用正负号、数码 0~7 表示，例如：0o27、0O36、-0o15。十六进制整数用 0x 或 0X 为前 缀，使用正负号、数字 0~9，a-f 表示，例如：0xff00、0xa5b4c3d2。
# 十进制数转换成二、八、十六进制数。
print(bin(1024))
print(oct(1024))
print(hex(1024))

print('*' * 100)


# 1.1.3 浮点型（float 类型）
#浮点型用来表示程序中用到的实数。整数和浮点数在计算机内部存储的方式是不同的，
#整数运算永远是精确的，而浮点数运算则可能会有四舍五入的误差。例如，3.14 是保留两位
#小数的浮点数值。
# 1. 小数形式
# 小数形式可以用来表示任意大小的实数，由正负号、数码 0~9 和小数点（必须有小数点）组成。
# 练习:使用浮点数描述学生身高、总评成绩、平均分、金额等信息。
print('我的身高(米)：', 1.76) # 使用逗号分隔输出项，输出时自动补一空格
print('综合测评成绩：', 90.5)
print('Python 课程全班平均成绩：', 85.6)
print('平均每月生活费：', 1080.5)

print('*' * 100)

# 1.1.4 布尔型（bool 类型）
# 布尔类型数据用来描述条件判断的结果，只有 True、False 两种值，分别表示“真”和
#“假”。True 和 False 的第 1 个字母必须大写，其他字母必须小写。
#布尔类型事实上是特殊的整型，True 对应整数值 1，False 对应整数值 0。当把其它类型
# 数据作为布尔值使用时，整数 0、浮点数 0.0、空字符串''、空值 None 等都被认为是 False， 其它值都被认为是 True。
# 练习: 使用字符串描述学生是否大于 18 岁、是否为团员的信息。
print('是否大于 18 岁：', True)
print('是否为团员：', False)
print('2020 年是闰年：', True)

print('*' * 100)


"""
1.1.5 空值型（NoneType 类型）
Python 中经常会遇到要测试数据是否为空的情形。Python 中空值一般用 None 表示。
None 是 Python 里的一个特殊值，表示该值是一个空对象，其类型为空值类型 NoneType，
None 也是 NoneType 数据类型的唯一值。None 的第 1 个字母必须大写，其他字母必须小写。
None 是一个特殊的常量。None 不能理解为 0，因为 0 是有意义的，而 None 是一个特
殊的空值。None 和 False 不同，None 也不是空字符串。
None 不支持任何运算，None 和任何其它数据类型比较永远返回 False。可以将 None 赋
值给任何变量，也可以给 None 值的变量赋值。如果希望变量中存储的东西不与任何其它值
混淆，就可以使用 None。
"""
# None值的使用
print(print("hello"))

print('*' * 100)

"""
【代码分析】该条语句先执行 print('Hello')，输出字符串“Hello”，再执行 print(print('Hello'))
输出 None，说明 print()函数的返回值为 None。
"""

"""
1.2 数据类型查看与转换
本小节主要学习如何查看数据类型以及数据类型之间的相互转换。通过不同示例的演示
与分析，重点学习查看数据类型函数、数据类型相互转换函数。
1.2.1 数据类型查看
1. type()函数
如果需要确定一个值的数据类型，可以使用 type()函数进行查看。
练习：type()函数查看值的数据类型。
"""
print(type(176), type('176'), type(1.76))
print(type(17e6))
print(type(True))
print(type(None))
print(type(print('Hello world')))

print('*' * 100)

"""
2. isinstance()函数
isinstance()函数根据两个参数的比对结果返回一个布尔值，第一个参数是待确定类型的
数据，第二个参数是指定进行比较的数据类型（int、str、float、bool 等等），返回值为 True
表示类型一致，False 表示类型不一致。
"""
print(isinstance(176, int), isinstance('176', str), isinstance(1.76, float))
print(isinstance(17e6, float))
print(isinstance(True, bool))
print(None is None)
print((print('Hello world') is None))

print('*' * 100)

"""
1.2.2 数据类型转换
Python 内置了一系列可实现强制类型转换的函数，这些函数返回一个新的对象，表示转
换后的值。数字间进行转换的函数有 int()、float()、bool()、str()等等。
当使用 int()函数将浮点数转换成整数时，小数部分会发生截断，而非四舍五入。可以使
用 type()函数验证数据是否类型转换成功。
"""
#【示例 1.2.2.1】数据类型转换。
print(type(1.76))
print(type(int(1.76))) # 浮点数转换成整数时，小数部分截断，而非四舍五入
print(int(1.76))
print(type(str(1.76)))

print('*' * 100)

"""
1.3 变量定义与运算
1.3.1 变量
之前的程序中输出的都是一些固定不变的数据。为了表示在程序运行过程中随时发生变
化的数据，Python 提供了变量。Python 使用不同的变量名标识不同的内存区域，通过变量名
访问和修改这些内存中存放的数据。实际上是内存中的数据有数据类型，变量本身没有数据
类型。
1. 变量赋值
每个变量在使用前都必须赋值，变量赋值以后该变量才会被创建。在 Python 中，变量
名可以看作是内存中值的标签，在程序中使用变量名，就是使用对应的值。变量定义格式如
下：
变量名 = 值
等号（=）运算符左边是一个变量名，等号（=）运算符右边是存储在变量中的值。“变
量名=值”称为赋值语句，可读为“将值赋给变量”，可以把任意数据类型赋值给变量。
"""
# 【示例 1.3.1.1】变量赋值。
studentName = '骆雄铠' # studentName 为字符串
print('姓名：' + studentName)
studentAge = 18 # studentAge 是整数
print('年龄：' + str(studentAge)) # +拼接输出时要先用 str()函数转成字符串

print('*' * 100)

# 关键信息需要理解
"""
最后一行打印出变量 myName 的内容到底是'贺峰'呢还是'Jerry'？如果从数学意义上理
解，就会错误地得出 myName 和 studentName 相同，也应该是'Jerry '，但实际上 myName 的
值是'贺峰'，一行一行分析执行代码，就可以发现：
studentName = '贺峰'
首先，计算机在内存中创建一个'贺峰'的字符串类型的对象，然后让这个对象与变量相
关联，即让 studentName 这个标签指向'贺峰'这个对象。当使用 print(studentName)输出时，
通过 studentName 就看到了'贺峰'这个对象，看似 studentName 就是'贺峰'，其实不然，只是
studentName 贴在了'贺峰'这个数据上
"""
studentName = '骆雄铠' 
myName = studentName
studentName = 'Jerry'
print(myName)

print('*' * 100)

# 【示例 1.3.1.3】为多个对象指定多个变量。
# 这种命名方式不推荐，不要用驼峰
myName, myAge, mySchool = 'john', 20, 'CCIT'
print(myName, myAge, mySchool)

# myName -> myname
# myAge -> myage
# mySchool -> myschool

# 推荐使用_来关联变量信息
my_name, my_age, my_school = 'john', 20, 'CCIT'

print('*' * 100)

"""
1.3.2 运算符
用来表示运算的符号称为运算符，使用 Python 语言中的运算符可以实现强大的数据运
算功能。Python 中的运算符主要包括：算术运算符、赋值运算符、比较运算符、逻辑运算符、
同一运算符和成员运算符。
1. 算术运算符
算术运算符用来完成对整数、浮点数的操作，并创建新对象。
算术运算符包括：+（加）、-（减）、*（乘）、**（乘幂）、/（除）、//（整除）、%（取余）。
a**b 表示求 a 的 b 次幂。
"""

# 算术运算。
numA, numB, numC = 7, -5.7, 2
resultSum, resultPower = numA + numB, numA ** numC
print('numA + numB=' + str(resultSum) + '\nnumA ** numC=' + str(resultPower))

print('*' * 100)

"""
【代码分析】第 2 行代码普通意义上的加法，7+（-5.7）出现的近似输出问题，是由于数据
在内存中采用二进制形式进行存储，而许多浮点数在用二进制表示时只能近似表示，不能精确表
示，因此，浮点数可能会出现误差。乘幂运算 7**2=72=49。
"""

# 试题：求两位正整数的各位数码。给定一个 2 位正整数 intNum，求 intNum 的十位和个位数码。
intNum = 48
numTens = intNum // 10 # 求十位数码
print('48 的十位数码是：' + str(numTens))
numOnes = intNum % 10 # 求个位数码
print('48 的个位数码是：' + str(numOnes))
print('*' * 100)
"""
【代码分析】第 2 行代码 48 // 10 表示取不大于 48 除以 10 的商的最大整数，即十位数码。
第 4 行代码 48 % 10 表示取 48 除以 10 后的余数，即个位数码。
注意：//、%运算时，当运算对象至少有一个浮点数时，结果为浮点型；当运算对象都为整数时，结果为整型。
"""

# 试题：布尔型数据进行算术运算。
print(True + True)
print(True * False)
"""
【代码分析】布尔类型事实上是特殊的整型，True、False 分别是数值 1 和 0 的另一种表示
方式，它们可以直接参与数值运算。True 对应整数值 1，False 对应整数值 0。
"""
print('*' * 100)


# 试题：字符串简单运算。
strStar = '_*_'
starCopy = strStar * 5 # 将 strStar 重复 5 次输出
print(starCopy)

print('*' * 100)


"""
2. 赋值运算符
在赋值运算中，我们常见到如下的式子：a = a+b，a = a-b，a = a*b，a = a**b，a = a/b，
a = a//b，a = a%b。以上式子可以分别缩写成：a+=b，a-=b，a*=b，a**=b，a/=b，a//=b，a%=b。
这样就产生一些新的运算符：+=，-=，*=，**=，/=，//=，%=，称为增强赋值运算符，它们
的意义与原来相同。赋值运算符实际上用来创建新对象和新对象的引用。
赋值运算符包括：=（赋值）、+=（加赋值）、-=（减赋值）、*=（乘赋值）、**=（乘幂赋
值）、/=（除赋值）、//=（整除赋值）、%=（取余赋值）。
"""

a = 0
a += 10
a += 10
a += 10
a += 10
a -= 10
print(a)

print('*' * 100)


# 试题：交换两个学生的专业值。
# 已知贺峰的专业是'软件技术'，马峰的专业是'云计算技术'，交换两个学生的专业。

studentMajor1, studentMajor2 = '软件技术', '云计算技术' 
print('贺峰专业：' + studentMajor1, '马峰专业：' + studentMajor2) 
temp = studentMajor1
studentMajor1 = studentMajor2
studentMajor2 = temp
print('贺峰新专业：' + studentMajor1, '马峰新专业：' + studentMajor2)

print('*' * 100)


"""
3. 比较运算符
比较运算符用于比较它两边的操作数，以判断操作数之间的某种关系是否成立，如果成
立，值为 True，否则，值为 False。
比较运算符包括：<（小于）、<=（小于等于）、>（大于）、>=（大于等于）、==（等于）、!=
（不等于）。
"""
# 比较运算:
# studentGrade = int(input('请输入 Python 成绩：')); # 若输入 85
studentGrade = 85; # 若输入 85
result = studentGrade >= 80
print('成绩大于或等于 80:' + str(result))
result = studentGrade == '85'
print("成绩与'85'相等:" + str(result))
resultCompare = result != 1
print('False 不是 1:'+ str(resultCompare))
print('data' <= 'date')

print('*' * 100)

"""
【代码分析】第 3 行代码使用“+”拼接输出时，因 result 值为布尔型，需用 str()函数转成字符串。
第 4 行代码 studentGrade 的类型是整数，而'85'是字符串，所以两者不等，返回 False。 第 5 行代码单双引号要交叉包含。
第 6 行代码布尔类型事实上是特殊的整型，True 对应整数值 1，False 不是 1。 第 8 行代码字母在比较时，默认是按照 ASCII 的大小比较的，即从字符串的第一个字符进
行比较，如果相等，则继续比较下一个字符，直到分出大小。前面字符都相同的情况下，较长的
那一个字符串大。
"""


"""
4. 逻辑运算符
逻辑运算符用于连接多个条件，构成更复杂的条件表达式。通常逻辑运算产生的结果是
一个 bool 值，如果条件为真，值为 True，否则，值为 False。
逻辑运算符包括：not（逻辑非）、and（逻辑与）、or（逻辑或）。
not True 返回 False，not False 返回 True。
and 运算符，当两个运算条件都为 True 时，返回 True；否则，有一个条件为 False 时，
返回 False。
or 运算符，当两个运算条件有一个为 True 时，返回 True；两个条件都为 False 时，才
返回 False
"""

# 逻辑运算符。
# studentGrade = int(input('请输入 Python 成绩：')); # 若输入 85
studentGrade = 85
result = studentGrade > 80 and studentGrade < 90
print('成绩大于 80 且小于 90:' + str(result)) 
result = 80 < studentGrade < 90 # 含义同第 2 行 5 print('成绩大于 80 且小于 90:' + str(result)) 6 result = not studentGrade > 90 or studentGrade>88
print('成绩不大于 90 或 85 大于 88:' + str(result)) 
# print(not 0 and 5) 
# print(3 or 5 and 8)

print('*' * 100)

"""
【代码分析】第 2 行代码表示在 85 在区间(80,90)内，返回 True。第 4 行代码是另一种写法，
含义同第 2 行，且更简便。 第 6 行代码 not 优先级高于 or，先计算 not 85>90，表示 85 不是大于 90 的，返回 True；
85>88，返回 False，最后 True or False=True。 第 8 行代码数字可以进行逻辑运算，逻辑非 not 的优先级别高于逻辑与 and，not 0 返回 True，
True and 5=5。 第 9 行代码逻辑与 and 的优先级别高于逻辑或 or，5 and 8=8，3 or 8=3。
需要注意：and 和 or 会短路运算(即只要能确定真假关系，就立即停止运算)，并返回运算的
结果(不是返回 True/False，而是返回表达式的运算结果)。
"""

"""
5. 同一运算符
同一运算符用于测试两个对象（或对象的引用）是否是同一个对象，通过比较两个对象
（或对象的引用）的标识 id 来确定。同一运算产生的结果是一个 bool 值，如果是同一个对
象，值为 True，否则，值为 False。
同一运算符包括： is（同一）、is not（不同一）。
"""
# 示例：
print(None is None)

#以成绩作为示例：
# studentGrade = int(input('请输入 Python 成绩：')); # 若输入 85
studentGrade = 85
print(studentGrade is '85') 
myGrade = 85
print(studentGrade is myGrade) 
print('id:')
print(id(studentGrade))
print(id(myGrade))
result = id(studentGrade) == id(myGrade)
print(result)

#【示例 1.3.2.9】同一运算符验证 None。 
emptyObj = None
print(emptyObj)
print(emptyObj is '')
print(emptyObj is False)

print('*' * 100)

"""
6. 成员运算符
成员运算符用于测试某个对象（或对象的引用）的值是否在指定的序列中，序列可以是
字符串、列表、元组、集合等（关于列表、元组、集合等知识，后面章节会有介绍）。成员
运算产生的结果是一个 bool 值，如果某个对象的值在指定的序列中，值为 True，否则，值
为 False。成员运算符包括： in、not in。
"""
#【示例 1.3.2.10】成员运算符。
key = 'ware'
department = 'Software and Big Data'
result = key in department
print(result)

print('*' * 100)
"""
6. Python 运算符优先级
Python 支持使用多个不同运算符连接表达式，实现相对复杂的功能，为了避免运算出现
歧义，Python 为每种运算符设定了优先级。
算术运算符的优先级别高于其他运算符；算术运算符的优先级别由高到低依次为：**（乘
幂）、+-（正负号）、*（乘）/（除）//（整除）%（取余）、+（加）-（减）。
比较运算符的优先级别低于算术运算符；所有比较运算符的优先级别相同。同一运算符
的优先级别与比较运算符相同。
逻辑运算符的优先级别较低，低于比较运算符，逻辑运算符的优先级别由高到低依次为：
not（逻辑非）、and（逻辑与）、or（逻辑或）。
"""

#运算符优先级。
studentGrade = 89
result = not studentGrade // 10 !=9 and studentGrade % 10 <= 5
print(result)

print('*' * 100)

"""
1.4 字符串处理
1.4.1 字符串截取
在实际编程应用中，经常需要对字符串进行截取。下面就结合示例说明字符串截取的用
法。Python 的子串列表有 2 种截取方式，区别在于取值的顺序：
从左到右索引默认 0 开始的，最大范围是字符串长度少 1；
从右到左索引默认-1 开始的，最大范围是负字符串长度。
从左到右索引和从右到左索引如图 1-4 所示。
1. 通过索引获取字符串中一个字符
"""

#操作符“[]”的使用。
course = 'Python'
print(course[1])
print(course[-4])
print(course[-1])
"""
运行显示为：
y
t
n
"""

print('*' * 100)

"""
2. [头索引:尾索引]截取字符串中的子串
如果要实现从字符串中获取一段子字符串的话，可以使用[头索引:尾索引]来截取相应的
字符串。当使用以冒号分隔的字符串截取时，Python 返回一个新的对象，获取的子字符串包
含头索引的字符，但不包含尾索引的字符。
获取子字符串时，若索引为空表示取到头或尾，具体说明如图 1-5 所示。从图中可以看
出：从前面开始截取时，取第一个字符可用[:1]表示；取前两个字符可用[:2]。从后面开始截
取是，取倒数第一个字符可用[-1:]；取倒数两个字符可用[-2:]。[:]表示取字符串的全部。
"""

print(course[1:3])

print('*' * 100)

# 操作符“[:]”的使用。
print(course[:])
print(course[2:]) # 从索引 2 开始往后取所有字符
print(course[:-2])

print('*' * 100)

"""
3. [头索引:尾索引:步长]截取字符串中的子串
Python 字符串截取可以接收第三个参数，参数作用是截取的步长。若未说明第三个参数
的值，则步长默认值为 1，具体说明如图 1-6 所示。
"""
# 操作符“[::]”的使用。
course = 'Python'
print(course[::]) # a、a[:]、a[::]相同
print(course[2:5:]) # 同 a[2:5]，步长默认为 1 
print(course[1::2]) # a[1:]中步长为 2 取字符
print(course[5:2:1]) # 头索引>=尾索引，值为空
print(course[5:2:-1]) # 从索引[5,2)中取字符，步长-1 表示从后往前取字符
print(course[5::-2]) # 从索引 5 开始，步长-2 表示从后往前隔一个取字符

print('*' * 100)

"""
1.4.2 字符串内置函数
字符串操作的内置函数有 len()、ord()、chr()、max()、min()等等。
1. 计算字符串长度函数 len()
字符串中含字符的个数称为该字符串的长度，Python 中使用 len()函数可以求得一个字
符串的长度。
"""
# 求字符串长度
print(len('Software and Big Data')) # 求字符串长度，单引号不是字符串内容
print(len('软件与大数据'))
print(len("I'm OK")) # 字符串中含有单引号，使用双引号来括

print('*' * 100)

"""
【代码分析】第 1 行代码用于括字符串的引号不是字符串中的字符，只起到区别其他对象
（变量）的作用，不是字符串的一部分，字符内的每一个空格算一个字符。
第 2 行代码字符串中的字符采用的是 Unicode 字符编码，可以包含中文字符，一个中文文字
算一个字符。
第 3 行代码'本身也是一个字符，含有单引号的字符串使用双引号""括起来，字符串"I'm OK"
包含 I，'，m，空格，O，K 这 6 个字符。
"""

"""
2. ASCII 数值与字符转换函数 ord()，chr()
ord()函数以一个字符（长度为 1 的字符串）作为参数，返回对应的 ASCII 码数值。chr()
函数（对于 8 位的 ASCII 字符串）是 ord()的配对函数，根据给定的 ASCII 码数值返回字符。
"""
# A用ord()与chr()
print(ord('A'))
print(chr(65))
print('*' * 100)

"""
3. 获得最大及最小 ASCII 值对应字符函数 max()和 min()
max()和 min()分别返回给定字符串中的 ASCII 码数值最大字符和 ASCII 码数值最小字
符。
"""
# max()、min()函数应用。
firstName = 'Zhao,Qian,Sun,Li'
print(max(firstName))
print(min(firstName))
print('*' * 100)
"""
1.4.3 字符串操作常用方法
使用 Python 提供的方法对字符串进行操作的基本语法为：
字符串变量名.方法名([参数列表])
1. 字符串大小写处理方法 capitalize()、casefold()、lower()、upper()、
swapcase()、title()
capitalize()方法将字符串首字母大写，其余部分小写； casefold()方法将字符串所有字母
转换成小写；lower()方法将字符串所有字母转换为小写字母，仅对 ASCII 编码的字母有效；
upper()方法将字符串所有字母变为大写；swapcase()方法将字符串 str 的大小写字母反转。
"""
# 转换会议名称文本大小写。
titleText = 'The 12th International Conference on Genetic and Evolutionary Computing'
print(titleText.capitalize())
print(titleText.casefold())
print(titleText.lower())
print(titleText.upper())
print(titleText.swapcase())
print(titleText.title())
print('*' * 100)

"""
2. 字符串组成判定方法 isalpha()、isdigit()、isalnum()
isalpha()方法判断字符串是否只由字母（英文字母+汉字）组成，空字符串返回 False；
isdigit()方法检测字符串是否只由数字组成；isalnum()方法判断字符串是否由字母或数字组成，
空字符串返回 False，中文按字母处理。
"""
# 判断密码和电话字符组成。
password = 'a1b2c3'
print(password.isalpha())
print(password.isalnum())
userPhone = '0519-86338226'
print(userPhone.isdigit())

print('*' * 100)

"""
【代码分析】第 2 行代码'a1b2c3'字符串中含有非字母字符（数字），所以返回值都为 False。
'abc'.isalpha()返回值为 True。 第 3 行代码'a1b2c3'字符串中只有字母和数字，所以返回 True。 第 4 行代码'0519-86338226'含有非数字字符（-），所以返回值都为 False。'051986338226'. 
isdigit()返回值为 True。
"""

"""
3. 字符串首尾删除特定内容方法 strip()、lstrip()、rstrip()
strip()方法用于移除字符串头尾指定的字符（默认为空格或换行符）或字符序列。注意：
该方法只能删除开头或是结尾的字符，不能删除中间部分的字符。lstrip() 方法用于截掉字
符串左边的空格或指定字符。rstrip()删除字符串末尾的指定字符（默认为空格）。
"""
# 去除用户名字符串空格
userName = ' system admin '
print(userName.strip())
print(userName.lstrip()) 
print(userName.rstrip())

print('*' * 100)

"""
4. 字符串首尾内容查找方法 startswith()、endswith()
startswith()用于检测字符串是否以指定字符串开头，如果是返回 True，否则返回 False。
endswith()函数用来判断字符串是否以指定字符或子字符串结尾。
"""
# 判断网址起始字符串。
website = 'http://www.ccit.js.cn' 
print(website.startswith('http://'))
print(website.endswith('.cn'))
print(website.startswith('www',7))

print('*' * 100)
"""
【代码分析】第 2-3 行代码判断 website 的值是否以“http://”开头、以“.com”结尾，均返回
True。第 4 行代码判断从索引为 7 的字符起是否以“www”开头，注意：字符串中第一个字符的
索引为 0。如果不指定，默认从头开始检索。
"""

"""
5. 字符串查找方法 find()、index()
find() 方法检测字符串中是否包含子字符串，如果指定检查范围，则在指定范围内检查，
如果包含子字符串，则返回出现字符的最小索引值，否则返回-1。
"""

# 使用 find()方法和 index()方法搜索子串。
course = 'software and hardware'
print(course.find('ware')) # 默认在整个字符串中找'ware'
print(course.index('ware')) # 默认在整个字符串中找'ware'
# print(course.index('er'))


print('*' * 100)


"""
【代码分析】第 2 行代码使用 find()方法在 course 中查找“ware”，返回出现的最小索引值 4。 第 3 行代码使用 index()方法，在 course 中查找“ware”，返回出现的最小索引值 4，同第 2 行。
第 4 行代码使用 index()方法尝试从 course 中找“er”，找不到子串，所以抛出 ValueError 异 常。index()与 find()方法功能相同，差别仅在于若不含子串会抛出 ValueError 异常。
"""
# 使用 find()方法和 index()方法搜索子串。
course = 'software and hardware'
print(course.find('ware', -8, -1))
print(course.find('ware', -8))
print(course.rfind ('ware', 1), course.rfind ('ware', -8, -1))
print(course.count('ware', 1), course.count('ware', -8, -1))

print('*' * 100)

"""
【代码分析】第 2 行代码尝试从 course[-8, -1)切片字符串（“hardwar'”）中找 “ware”，找不
到，返回-1。 第 3 行代码从 course[-8:]切片字符串（“hardware'”）中找“ware”，返回出现的索引值 17。 第 4 行代码返回子串“ware”在字符串 course[1:]切片字符串(“oftware and hardware”)最后一
次出现的位置，返回出现的索引值 17。尝试从 course[-8, -1)切片字符串（“hardwar'”）中找到“ware”，
找不到子串，返回-1。 第 5 行代码返回子串“ware”在 course[1:]切片字符串(“oftware and hardware”)中出现的次
数，值为 2。返回子串“ware”在 course[-8, -1)切片字符串（“hardwar'”）中出现的次数，找不到子
串，返回 0。
"""

"""
6. 字符串内容替换方法 replace()
replace()方法把字符串中的旧字符串替换成新字符串，如果指定第三个参数 max，则替
换不超过 max 次。
"""
# 使用 replace()方法替换字符串。
department = 'Software and Big Data'
print(department.replace('Big Data', 'Cloud Computing'))
course = 'Software and Hardware'
print(course.replace('w', 'W', 2))
print('*' * 100)

"""
7. 字符串分割方法 split()
split()方法通过指定分隔符（第一个参数）对字符串进行切片，如果第二个参数 num 有
指定值，则分隔 num+1 个子字符串。若第一个参数未指定，表示按照空格来切片。
"""
# 使用 split()方法切片字符串。
str = 'Life is short , I use python '
print(str.split()) # 返回值为列表
website = 'www.baidu.com '
print(website.split('.', -1))
strWeb, strDomain = website.split('.', 1)
print(strWeb, strDomain) 
strOS= 'WinXP||Win7||Win8||Win8.1'
print(strOS.split('||', 2))

print('*' * 100)

"""
【代码分析】第 2 行代码使用 split()方法，使用默认分隔字符（空格）对一个字符串进行切 片，返回的是切片之后的单词列表，有关列表知识后面章节介绍。
第 4 行代码以“.”为分隔符对字符串进行切片，-1 表示对切片数量没有限制。
第 5 行代码以“.”为分隔符对字符串进行切片，第二个参数 1 表示有 1 个切片后，剩下的
所有字符放在一起作为最后一个切片。此时，字符串切成 2 部分，分别赋值给变量 strWeb, 
strDomain。 第 8 行代码以“||”为分隔符对字符串进行切片，第二个参数 2 表示有 2 个切片后，剩下的
所有字符放在一起作为最后一个切片。
"""

"""
8. 字符串拼接方法 join()
join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
"""
# 使用 join()方法拼接文件路径。
path = 'c: system todo f.txt'
print('/'.join(path.split()))

print('*' * 100)
"""
【代码分析】第 2 行代码先以空格为分隔符，将 path 切分，再以“/”连接。
本小节的重点和难点在于，实际应用中，使用不同的方式创建并处理字符串，理解函数
和方法在使用时语法上的区别，各个函数和方法参数的含义，根据示例讲解进行灵活运用。
"""

# 不使用格式化输出的例子
a = '1'
b = '2'
c = '3'
print("a = ?, b = ?, c = ?")
print("a = " + a + ",b = " + b + ",c ="+ c)
print('*' * 100)

"""
1.5 格式化输出
本小节主要学习使用字符串格式化来生成格式固定但数据不完全相同的字符串。Python
语言中，有多种方式可以实现字符串的格式化，可以使用 print()函数的参数来控制，或者使
用格式化字符和 raw 字符、格式符（%）、format()方法、f 字符串等方式来实现。
通过不同示例的演示与分析，重点学习这些格式化方法的基本原理与使用。
"""

"""
print函数的使用
使用 print()函数的一些参数可以实现简单的数据格式化输出。
1. print()函数参数
前面代码中的输出都是通过函数 print()实现的，该函数还可以有 2 种类型的参数，sep
和 end。
"""
# print()函数及其参数使用。
print('input', 'output', sep = '&') # 输出项之间用&分隔
print() # 参数为空，输出一个空行，起到换行作用
print('input', 'output', sep = '&', end = '……') # 输出结尾符号为……
print('*' * 100)
"""
【代码分析】第 1 代码 sep 指定字符(&)作为前面 3 个参数输出的分隔符。
第 2 行代码 print()参数为空，表示输出一个空行，一般用来表示换行功能。
第 3 行代码输出项之间使用空格隔开，整个输出内容以“……”结尾，输出项也可以使用单
引号括起来，在 Python 的 print()函数中，单引号或双引号都可以输出字符串。
"""

a = 'adsfjsdklfjdl, '+ \
    'ashjdfjkshfjkds '+ \
    '111222'
print(a) 
print('*' * 100)

"""
3. 转义字符
如果一个字符串内部既包含'又包含"，使用之前的单双引号交叉包含无法实现，可以用
转义字符\来标识，比如：'I\'m \"OK\"!'表示的字符串内容是：I'm "OK"!
以反斜杠“\”开头，后跟一个规定的字符或数字串，用来表示一个字符，我们把这种表示
形式称为转义字符，比如\n 表示换行，\t 表示制表符，字符\本身也要转义，所以\\表示字符
\。
"""
# 转义字符。
print('I\'m \"OK\"!')
print('\t 个人信息')
print('\nstudentAge=20')
print('c:\now') 
print('c:\\now')

print('*' * 100)

"""
【代码分析】第 1 行代码字符串中，\'输出'，\"输出"。 第 2 行代码\t 输出水平制表，接着再输出“个人信息”。
第 3 行代码\n 输出换行符，接着再下一行输出“studentAge=20”。
第 4 行代码字符串中的\n 输出了换行符，所以先输出“c:”，下一行输出“ow”。 第 5 行代码\\转义输出为\，最终为“c:\now”。
常见的转义字符及含义详见“表 1-5 转义字符及含义”。
"""

"""
4. raw 字符串
如果字符串中包含很多个反斜杠，代码显得比较混乱，为了简化，可以使用 raw 字符串。
在字符串前面加个前缀 r，表示这个字符串是一个 raw 字符串，里面的转义字符将不被
转义。
"""
# raw 字符串。
print('\\\t\\') # 需转义
print(r'\\\t\\') # raw 字符，无需转义
print(r'''Python 的设计哲学是“优雅”、“明确”、“简单”。
Python 的设计目标之一是让代码具备高度的可阅读性。''')

print('*' * 100)

"""
【代码分析】第 1 行代码需要转义输出字符，\\输出为\，\t 输出一个制表符。
第 2 行代码输出一个 raw 字符，无需转义，按原样输出。
第 3-4 行代码 r'''……'''之间的内容按原样输出，包括引号和换行。
"""

"""
1.5.2 格式化操作符%
使用操作符“%”进行字符串格式化是一种常见的方法。
计算机程序常常会处理或输出具有固定格式的内容，如：
姓名：贺峰，年龄：20，身高：1.75
假设以上内容横线处的字符是变化的，其余部分的格式是固定的。
使用格式符“%”对字符串进行格式化时，Python 会使用一个带有格式符的字符串作为模
板，用于为真实值预留位置，并说明真实数值应该呈现的格式。基本语法为：
print(格式化字符串 % (输出表列))
包括格式化字符串和输出表列两部分，中间用“%”隔开。其中，格式化字符串由“%”开
头，后跟修饰符及格式字符。
"""
# 格式化操作符%使用。
print('姓名：%s，年龄：%d，身高：%f' % ('贺峰', 20, 1.75))
print('*' * 100)
"""
【代码分析】
(1) '姓名：%s，年龄：%d，身高：%f'为要输出的格式化字符，也可以用双引号括起来，其
中根据输出的数值格式，分别使用%s、%d、%f 进行占位，并说明后面的输出项对应按占位指定
格式输出。
(2) ('贺峰', 20, 1.75)为填入格式占位符的真正数值，输出项之间用逗号分隔，输出项可以是
常量、变量、表达式等，输出项的个数必须与格式说明的个数相同。
"""

"""
1.5.3 format()方法格式化字符串
百分号“%”格式化字符串，只能对整型、浮点型和字符串类型进行格式化，具有一定的
局限性，而且当需要格式化的字符串较长，输出项较多时，代码冗长、不易读、易出错。为
克服这一问题，使用 format()方法对字符串格式化更加规范。format()方法调用格式：
模板字符串. format(参数 1, 参数 2, …, 参数 n)
模板字符串调用 format()方法使用“.”运算符，format()方法中的参数可以是常量、变量、
表达式，甚至可以是函数调用。通常与 print()函数配合使用在程序中实现格式化输出。
"""
# 计算圆的面积和周长，并使用 format()方法格式化输出结果。
r = 3
area = 3.14 * r * r
perimeter = 3.14 * 2 * r 
print("面积：{0}，周长：{1}".format(area, perimeter))
print("面积：{}，周长：{}".format(area, perimeter)) # 省略序号，默认替换
print("面积：{key}，周长：{0}".format(perimeter, key=area)) # 序号和关键字使用

print('*' * 100)

"""
格式规范用于规定 format()方法中对应参数值的替换方式，由[[填充]对齐][符号][#][域 宽][,][ .精度][类型]按顺序组成，格式规范所使用的字符及含义与 format()函数格式规范字符
相同，详见“表 1-8 format()方法格式规范常见字符及含义”。
"""

"""
1.5.4 f 字符串格式化字符串
format()方法对字符串格式化解决了使用百分号“%”格式化字符串具有局限性的问题，
但仍然存在代码冗长的问题。自 Python3.6 版本开始推出了使用 f 字符串对字符串格式化，
与其它格式化方法相比，它不仅更简洁，更易读，不易出错，而且速度快。
1. f 字符串格式：
以字母 f 开头，f 可以小写也可以大写，格式字符串是用单引号或双引号或三引号（三
个单引号）引起的字符串。
2. 格式字符串：格式字符串包括文本文字或替换字段{}。
非替换字段的文字为文本文字，文本文字按原样处理，文本文字和替换字段{}都可以含
有多个。
3. 替换字段格式：{表达式[:格式规范]}
格式规范用来指定表达式值的替换方式，由[[填充]对齐][符号][#][域宽][,][ .精度][类型]
按顺序组成，格式规范所使用的字符及含义与 format()方法格式规范字符相同，详见“表 1-8 format()方法格式规范常用字符及含义”。
"""
# f 字符串格式化字符串。
r = 3
area = 3.14 * r * r
perimeter = 3.14 * 2 * r 
print(f"面积：{area}，周长：{perimeter}")
print(f"面积：{area}，周长：{perimeter:>10}") # 用 10 位居右方式输出
print(f"面积：{ area:.1f}，周长：{perimeter:#^7}")
result='面积：530.7，周长：#81.64#' 
print(f"{result:.8s}")